package com.gitee.qdbp.base.controlling;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitee.qdbp.able.beans.AcceptAttrs;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.base.enums.OperateType;
import com.gitee.qdbp.base.system.service.IDefaultValueConfig;

/**
 * 按字段(或数据类型)注册AcceptAttrsHandler
 *
 * @author zhaohuihua
 * @version 170714
 */
public class DataIsolationChooseControlling extends DataIsolationSimpleControlling {

    private static final Logger log = LoggerFactory.getLogger(DataIsolationChooseControlling.class);

    private IDefaultValueConfig defaultValues;

    /** 未找到处理器时是否报错 **/
    private boolean throwErrorOnHandlerNotFound;

    /** 默认处理器, 在未找到字段处理器时调用 **/
    private IAcceptAttrsHandler defaultHandler;

    /** 按字段注册的处理器 **/
    private Map<String, IAcceptAttrsHandler> byField;
    /** 按表名+字段注册的处理器 **/
    private Map<String, IAcceptAttrsHandler> byDataType;

    public DataIsolationChooseControlling() {
        throwErrorOnHandlerNotFound = true;
        byField = new HashMap<>();
        byDataType = new HashMap<>();
    }

    public void setDefaultValueConfig(IDefaultValueConfig defaultValues) {
        this.defaultValues = defaultValues;

        if (this.defaultHandler instanceof IDefaultValueConfig.Aware) {
            IDefaultValueConfig.Aware aware = (IDefaultValueConfig.Aware) this.defaultHandler;
            aware.setDefaultValueConfig(defaultValues);
        }

        for (Map.Entry<String, IAcceptAttrsHandler> entry : this.byField.entrySet()) {
            if (entry.getValue() instanceof IDefaultValueConfig.Aware) {
                ((IDefaultValueConfig.Aware) entry.getValue()).setDefaultValueConfig(defaultValues);
            }
        }

        for (Map.Entry<String, IAcceptAttrsHandler> entry : this.byDataType.entrySet()) {
            if (entry.getValue() instanceof IDefaultValueConfig.Aware) {
                ((IDefaultValueConfig.Aware) entry.getValue()).setDefaultValueConfig(defaultValues);
            }
        }
    }

    /** 设置默认处理器, 在未找到字段处理器时调用 **/
    public IAcceptAttrsHandler setDefaultHandler(IAcceptAttrsHandler handler) {
        IAcceptAttrsHandler old = this.defaultHandler;
        if (handler instanceof IDefaultValueConfig.Aware) {
            ((IDefaultValueConfig.Aware) handler).setDefaultValueConfig(defaultValues);
        }
        this.defaultHandler = handler;
        return old;
    }

    /** 获取默认处理器 **/
    public IAcceptAttrsHandler getDefaultHandler() {
        return defaultHandler;
    }

    /** 获取字段处理器 **/
    public Map<String, IAcceptAttrsHandler> getFieldHandlers() {
        return byField;
    }

    /** 获取字段处理器 **/
    public void setFieldHandlers(Map<String, IAcceptAttrsHandler> handlers) {
        for (Map.Entry<String, IAcceptAttrsHandler> entry : handlers.entrySet()) {
            if (entry.getValue() instanceof IDefaultValueConfig.Aware) {
                ((IDefaultValueConfig.Aware) entry.getValue()).setDefaultValueConfig(defaultValues);
            }
        }
        this.byField = handlers;
    }

    /** 设置指定字段的处理器 **/
    protected IAcceptAttrsHandler addFieldHandler(String field, IAcceptAttrsHandler handler) {
        if (handler instanceof IDefaultValueConfig.Aware) {
            ((IDefaultValueConfig.Aware) handler).setDefaultValueConfig(defaultValues);
        }
        return this.byField.put(field, handler);
    }

    /** 获取数据类型处理器 **/
    public Map<String, IAcceptAttrsHandler> getDataTypeHandlers() {
        return byDataType;
    }

    /** 设置数据类型处理器 **/
    public void setDataTypeHandlers(Map<String, IAcceptAttrsHandler> handlers) {
        for (Map.Entry<String, IAcceptAttrsHandler> entry : handlers.entrySet()) {
            if (entry.getValue() instanceof IDefaultValueConfig.Aware) {
                ((IDefaultValueConfig.Aware) entry.getValue()).setDefaultValueConfig(defaultValues);
            }
        }
        this.byDataType = handlers;
    }

    /** 设置指定数据类型的处理器 **/
    protected IAcceptAttrsHandler addDataTypeHandler(String dataType, IAcceptAttrsHandler handler) {
        if (handler instanceof IDefaultValueConfig.Aware) {
            ((IDefaultValueConfig.Aware) handler).setDefaultValueConfig(defaultValues);
        }
        return this.byDataType.put(dataType, handler);
    }

    /** {@inheritDoc} **/
    @Override
    protected AcceptAttrs<?> getAcceptAttrs(Object o, Field field, String dataType, OperateType operateType)
            throws ServiceException {

        String fieldName = field.getName();

        // 先按表+字段名查找, 再按字段名查找, 最后查找默认处理器
        IAcceptAttrsHandler handler = null;
        String tableAndField = dataType + "." + fieldName;
        if (byDataType.containsKey(tableAndField)) {
            handler = byDataType.get(tableAndField);
        } else if (byField.containsKey(fieldName)) {
            handler = byField.get(fieldName);
        } else {
            handler = defaultHandler;
        }

        if (handler != null) { // 获取数据隔离的权限属性
            return handler.getAcceptAttrs(o, field, dataType, operateType);
        } else {
            if (throwErrorOnHandlerNotFound) {
                log.error("Unsupported data isolation for {}.{}", o.getClass().getSimpleName(), fieldName);
                throw new ServiceException(ResultCode.UNSUPPORTED_OPERATION);
            } else {
                return null;
            }
        }
    }

    /** 未找到处理器时是否报错 **/
    public boolean isThrowErrorOnHandlerNotFound() {
        return throwErrorOnHandlerNotFound;
    }

    /** 未找到处理器时是否报错 **/
    public void setThrowErrorOnHandlerNotFound(boolean throwErrorOnHandlerNotFound) {
        this.throwErrorOnHandlerNotFound = throwErrorOnHandlerNotFound;
    }

}
